#[cfg(target_os = "windows")]
use build_migrate::script_runner::ScriptRunner;
use std::path::PathBuf;

/// 测试脚本执行器的基本功能
#[test]
#[cfg(target_os = "windows")]
fn test_script_runner_basic() {
    let script_path = PathBuf::from("tests/scripts/test_env.bat");

    // 确保测试脚本存在
    assert!(script_path.exists(), "测试脚本不存在: {}", script_path.display());

    let runner = ScriptRunner::new(None, false);
    let result = runner.run_scripts(&[script_path]);

    assert!(result.is_ok(), "脚本执行失败: {:?}", result.err());

    let env_vars = result.unwrap();

    // 调试：打印所有捕获的环境变量
    eprintln!("捕获到 {} 个环境变量", env_vars.len());
    eprintln!("TEST_VAR1: {:?}", env_vars.get("TEST_VAR1"));
    eprintln!("TEST_VAR2: {:?}", env_vars.get("TEST_VAR2"));
    eprintln!("PATH: {:?}", env_vars.get("PATH").map(|s| &s[..50.min(s.len())]));

    // 验证环境变量是否被正确捕获
    assert!(env_vars.contains_key("TEST_VAR1"), "TEST_VAR1 未被捕获");
    assert_eq!(env_vars.get("TEST_VAR1").unwrap(), "value1");

    assert!(env_vars.contains_key("TEST_VAR2"), "TEST_VAR2 未被捕获");
    assert_eq!(env_vars.get("TEST_VAR2").unwrap(), "value2");

    assert!(env_vars.contains_key("TEST_PATH"), "TEST_PATH 未被捕获");
    assert_eq!(env_vars.get("TEST_PATH").unwrap(), "C:\\test\\path");

    assert!(env_vars.contains_key("NUMERIC_VAR"), "NUMERIC_VAR 未被捕获");
    assert_eq!(env_vars.get("NUMERIC_VAR").unwrap(), "12345");
}

/// 测试多个脚本按顺序执行
#[test]
#[cfg(target_os = "windows")]
fn test_multiple_scripts() {
    // 创建临时测试脚本
    use std::fs;
    use std::io::Write;
    use std::time::{SystemTime, UNIX_EPOCH};

    let temp_dir = std::env::temp_dir();
    let timestamp = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_nanos();
    let script1_path = temp_dir.join(format!("test_script1_{}.bat", timestamp));
    let script2_path = temp_dir.join(format!("test_script2_{}.bat", timestamp + 1));

    // 第一个脚本设置 VAR_A 和 VAR_COMMON
    let mut file1 = fs::File::create(&script1_path).unwrap();
    writeln!(file1, "@echo off").unwrap();
    writeln!(file1, "set VAR_A=from_script1").unwrap();
    writeln!(file1, "set VAR_COMMON=script1").unwrap();
    drop(file1);

    // 第二个脚本设置 VAR_B 并覆盖 VAR_COMMON
    let mut file2 = fs::File::create(&script2_path).unwrap();
    writeln!(file2, "@echo off").unwrap();
    writeln!(file2, "set VAR_B=from_script2").unwrap();
    writeln!(file2, "set VAR_COMMON=script2").unwrap();
    drop(file2);

    eprintln!("Script1: {}", script1_path.display());
    eprintln!("Script2: {}", script2_path.display());

    let runner = ScriptRunner::new(None, false);
    let result = runner.run_scripts(&[script1_path.clone(), script2_path.clone()]);

    // 清理临时文件
    let _ = fs::remove_file(&script1_path);
    let _ = fs::remove_file(&script2_path);

    assert!(result.is_ok(), "多脚本执行失败: {:?}", result.err());

    let env_vars = result.unwrap();

    eprintln!("VAR_A: {:?}", env_vars.get("VAR_A"));
    eprintln!("VAR_B: {:?}", env_vars.get("VAR_B"));
    eprintln!("VAR_COMMON: {:?}", env_vars.get("VAR_COMMON"));

    // 验证两个脚本的变量都被捕获
    assert!(env_vars.contains_key("VAR_A"), "VAR_A 未被捕获");
    assert_eq!(env_vars.get("VAR_A").unwrap(), "from_script1");
    assert!(env_vars.contains_key("VAR_B"), "VAR_B 未被捕获");
    assert_eq!(env_vars.get("VAR_B").unwrap(), "from_script2");

    // 验证后执行的脚本会覆盖前面的同名变量
    assert_eq!(env_vars.get("VAR_COMMON").unwrap(), "script2");
}

/// 测试脚本执行失败时的错误处理
#[test]
#[cfg(target_os = "windows")]
fn test_script_failure_handling() {
    use std::fs;
    use std::io::Write;
    use std::time::{SystemTime, UNIX_EPOCH};

    let temp_dir = std::env::temp_dir();
    // 使用时间戳确保文件名唯一
    let timestamp = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_nanos();
    let failed_script = temp_dir.join(format!("test_failed_script_{}.bat", timestamp));

    // 创建一个会失败的脚本（返回退出码 1）
    let mut file = fs::File::create(&failed_script).unwrap();
    writeln!(file, "@echo off").unwrap();
    writeln!(file, "exit /b 1").unwrap();
    drop(file); // 确保文件被正确关闭

    eprintln!("失败脚本路径: {}", failed_script.display());

    // 测试默认行为（失败时中止）
    let runner = ScriptRunner::new(None, false);
    let result = runner.run_scripts(&[failed_script.clone()]);

    eprintln!("失败测试结果: {:?}", result);
    assert!(result.is_err(), "预期脚本执行失败但却成功了");

    // 测试 continue_on_error 行为
    let runner_continue = ScriptRunner::new(None, true);
    let result_continue = runner_continue.run_scripts(&[failed_script.clone()]);

    // 清理临时文件
    let _ = fs::remove_file(&failed_script);

    // 即使脚本失败，因为 continue_on_error = true，也应该返回 Ok
    assert!(result_continue.is_ok(), "continue_on_error 模式下应该返回 Ok");
}

/// 测试脚本不存在时的错误处理
#[test]
#[cfg(target_os = "windows")]
fn test_nonexistent_script() {
    let nonexistent_script = PathBuf::from("nonexistent_script.bat");

    let runner = ScriptRunner::new(None, false);
    let result = runner.run_scripts(&[nonexistent_script]);

    assert!(result.is_err(), "预期因脚本不存在而失败");
}

/// 测试工作目录配置
#[test]
#[cfg(target_os = "windows")]
fn test_working_directory() {
    use std::fs;
    use std::io::Write;
    use std::time::{SystemTime, UNIX_EPOCH};

    let temp_dir = std::env::temp_dir();
    let timestamp = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_nanos();
    let test_dir = temp_dir.join(format!("script_test_workdir_{}", timestamp));
    fs::create_dir_all(&test_dir).unwrap();

    let script_path = test_dir.join("test_workdir.bat");

    // 创建一个输出当前目录的脚本
    let mut file = fs::File::create(&script_path).unwrap();
    writeln!(file, "@echo off").unwrap();
    writeln!(file, "set CURRENT_DIR=%CD%").unwrap();
    drop(file);

    eprintln!("测试目录: {}", test_dir.display());
    eprintln!("脚本路径: {}", script_path.display());

    let runner = ScriptRunner::new(Some(test_dir.clone()), false);
    let result = runner.run_scripts(&[script_path.clone()]);

    // 清理临时文件和目录
    let _ = fs::remove_file(&script_path);
    let _ = fs::remove_dir(&test_dir);

    assert!(result.is_ok(), "工作目录测试失败: {:?}", result.err());

    let env_vars = result.unwrap();

    eprintln!("CURRENT_DIR: {:?}", env_vars.get("CURRENT_DIR"));

    // 验证工作目录被正确设置
    assert!(env_vars.contains_key("CURRENT_DIR"), "CURRENT_DIR 未被捕获");
}

/// 测试配置文件中的脚本配置解析
#[test]
fn test_script_config_parsing() {
    use build_migrate::config::Config;
    use std::fs;
    use std::io::Write;
    use std::time::{SystemTime, UNIX_EPOCH};

    let temp_dir = std::env::temp_dir();
    let timestamp = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_nanos();
    let config_path = temp_dir.join(format!("test_script_config_{}.toml", timestamp));

    let config_content = r#"
input_path = "test.vcxproj"
generator = "xmake"
log_level = "info"

[pre_migration_scripts]
scripts = ["script1.bat", "script2.bat"]
working_directory = "C:/test"
continue_on_error = true
"#;

    let mut file = fs::File::create(&config_path).unwrap();
    write!(file, "{}", config_content).unwrap();
    drop(file);

    let config = Config::from_file(&config_path).unwrap();

    // 清理临时文件
    let _ = fs::remove_file(&config_path);

    // 验证配置被正确解析
    assert_eq!(config.pre_migration_scripts.scripts.len(), 2);
    assert_eq!(config.pre_migration_scripts.scripts[0], PathBuf::from("script1.bat"));
    assert_eq!(config.pre_migration_scripts.scripts[1], PathBuf::from("script2.bat"));
    assert_eq!(config.pre_migration_scripts.working_directory, Some(PathBuf::from("C:/test")));
    assert_eq!(config.pre_migration_scripts.continue_on_error, true);
}
